package com.da.landlord;

import java.math.BigDecimal;
import java.sql.Timestamp;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.List;

import javax.annotation.Resource;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.stereotype.Service;

import com.da.finance.DaFinanceCategory;
import com.da.finance.DaFinanceStatement;
import com.da.finance.DaFinanceStatementService;
import com.espirit.eap.sa.LoginUser;
import com.googlecode.cswish.annotation.Rest;
import com.googlecode.cswish.model.PageInfo;
import com.googlecode.cswish.oosearch.Condition;
import com.googlecode.cswish.oosearch.QLInfo;
import com.googlecode.cswish.struts.spring.GenericService;
import com.ra.external.FinanceStatementService;
import com.ra.landlord.LandlordOwnerUser;
import com.ra.landlord.LandlordUser;
import com.ra.landlord.LandlordUserService;
import com.ra.landlord.TenantUser;
import com.ra.landlord.constant.LandlordConstant;
import com.ra.landlord.vo.OrderItemsVO;
import com.ra.landlord.vo.OrderVO;
import com.ra.order.OrderUtil;
import com.ra.order.rental.RentalOrder;
import com.ra.pay.PaymentRecord;
import com.ra.util.CommonService;
import com.ra.util.RaConstant;
import com.ra.util.SmsLog;
import com.ra.util.SmsService;

/**
 * 
 * 但网上收租成功过后，需要使用此接口调用相应的通知方法进行最终确认"已支付"
 * @author PeterZ
 *
 */
@Service
public class PaidNoticeService {
	
	private static final Log logger = LogFactory.getLog(DaConfirmMoneyService.class);

	@Resource
	private GenericService genericService;
	
	@Resource
	private DaFinanceStatementService daFinanceStatementService;
	
	@Resource
	private DaChargeItemService daChargeItemService;
	
	@Resource
	private LandlordUserService landlordUserService;
	
	@Resource
	private FinanceStatementService financeStatementService;
	
	@Resource
	private SmsService smsService;
	
	@Resource
	private CommonService commonService;
	
	
	
	/**
	 * 网上支付成功过后调用此方法 此方法不会去改变RentalOrder的状态
	 * 功能：1.改变RentalOrder对应的chargeItems的状态为已交租
	 * 		2.产生一笔收费记录单
	 * 		3.产生一笔财务流水
	 *      4.产生下一个周期应收取的房租到chargeItem表中
	 * @param rentalOrder 已支付完成的定单
	 * @param tradeType  支付类型
	 */
	@Rest(type = "update")
	public void paidNotice(RentalOrder rentalOrder,Integer tradeType,String outTradeNo){
		
		rentalOrder = genericService.load(rentalOrder);
		
		DaChargeBillRecord chargeBillRecord = rentalOrder.getChargeBillRecord();
		chargeBillRecord.setStatus(DaChargeBillRecord.STATUS_RENT_DONE);
		
		List<DaChargeItem> orderItems = chargeBillRecord.getChargeItems();
		if(null == orderItems || orderItems.size() == 0){
			String errStr = "no data be found!";
			logger.error(errStr);
			return;
		}
		for (DaChargeItem daChargeItem : orderItems) {
			daChargeItem.setStatus(DaChargeItem.STATUS_PAID);
			daChargeItem = genericService.merge(daChargeItem);//可去掉
		}
		genericService.merge(chargeBillRecord);
		
		tradeType = tradeType==null?DaFinanceStatement.TRADE_TYPE_CRASH:tradeType;
		
		createBill(rentalOrder);
		daFinanceStatementService.addInternal(rentalOrder.getDaRoom(), rentalOrder.getTotalFee(),DaFinanceCategory.FINANCE_CATEGORY_RENT, new Date(), tradeType, "房租");
		daChargeItemService.generateChargeBillRecord(rentalOrder.getDaRoom());
		
	}
	
	
	
	/**
	 * 判断是否支付的是分散式的房源，如果是，请不要再做任何处理,因为本方法已经处理过了。
	 * @param outTradeNo
	 * @param customerTradeNo
	 * @param payType
	 * @return
	 */
	public boolean isPaidFromDaRoom(String outTradeNo,String customerTradeNo,int payType){
		
		RentalOrder rentalOrder = new RentalOrder();
		rentalOrder.setOutTradeNo(outTradeNo);
		rentalOrder = genericService.searchAll(rentalOrder).getData(0);
		
		if(null == rentalOrder ||  null == rentalOrder.getId())
			return false;
		
		if(!LandlordConstant.ROOMTYPE_DA.equals(rentalOrder.getRoomType())){
			return false;
		}
		
		PaymentRecord payModel =createPaymentRecord(rentalOrder,outTradeNo,customerTradeNo,payType);
		rentalOrder.setPaymentRecord(payModel);
		rentalOrder.setOrderState(RentalOrder.ORDER_STATE_PAYMENTED);
		rentalOrder.setHhzPay(true);
		genericService.merge(rentalOrder);
		sendMsg(rentalOrder);
		
		paidNotice(rentalOrder,payType,outTradeNo);
		// 参加活动获取交租补贴，财务流水
		attendActivityHandleOfDa(rentalOrder);
		return true;
	}
	
	private void attendActivityHandleOfDa(RentalOrder rentalOrder){
		DaRoom room = rentalOrder.getDaRoom();
		LandlordUser landlordUser = room.getLandlordUser();
		if (landlordUser.getAttendMilliActivity() != null && landlordUser.getAttendMilliActivity()) {
			RentalOrder newRentalOrder = new RentalOrder();
			newRentalOrder.setTotalFee(RentalOrder.ACTIVITY_AMOUNT);
			newRentalOrder.setOrderDec(RentalOrder.ACTIVITY_NAME);
			//newRentalOrder.setFeeRecord(rentalOrder.getFeeRecord());
			addRentalOrderOfActivityOfDa(newRentalOrder,rentalOrder);
			logger.info("新增百万活动在线交租房东补贴订单(分散式房源)");
			// 新增财务流水
			financeStatementService.createActivityStatementOfDa(room, RentalOrder.ACTIVITY_AMOUNT, RentalOrder.ACTIVITY_NAME);
			logger.info("新增百万活动房东交租财务流水记录(分散式房源)");
		}
	}
	
	/**
	 * 百万活动，租客在线交租，即给房东生成一笔补贴订单
	 * 参数必须设置model.setFeeRecord()、model.setTotalFee()、model.setOrderDec
	 * 
	 * @param model
	 * @return
	 */
	public RentalOrder addRentalOrderOfActivityOfDa(RentalOrder model, RentalOrder rentalOrder){
		Date date = Calendar.getInstance().getTime();
		model.setCreateTime(new Timestamp(date.getTime()));
		// admin
		LandlordOwnerUser landlordUser = rentalOrder.getDaRoom().getLandlordUser();
		model.setCreateUser(landlordUser);
		model.setOrderState(RentalOrder.ORDER_STATE_PAYMENTED);
		// 商品订单号
		String outTradeNo = OrderUtil.getOrderNum();
		model.setOutTradeNo(outTradeNo);
		
		// 订单名称
		String orderName = rentalOrder.getOrderName().replace("总费用", "交租补贴");
		model.setOrderName(orderName);
		
		// 设置房源信息
		model.setDaRoom(rentalOrder.getDaRoom());
		
		//补贴类型
		model.setOrderType(RentalOrder.ORDERTYPE_ACTIVITY);
		
		return genericService.add(model);
	}
	
	/**
	 * 收租成功 信息发送
	 * @param rentalOrder
	 */
	public void sendMsg(RentalOrder rentalOrder){
		
		Calendar cal = Calendar.getInstance();
		int month = cal.get(Calendar.MONTH) + 1;
		int day = cal.get(Calendar.DAY_OF_MONTH);
		int hour = cal.get(Calendar.HOUR);
		int minute = cal.get(Calendar.MINUTE);
		
		LandlordOwnerUser landlordUser =  rentalOrder.getDaRoom().getLandlordUser();
		String phone =landlordUser.getPhone();
		LoginUser loginUser = landlordUser.getLoginUser();
		
		Date startDate =rentalOrder.getChargeBillRecord().getDateBeginRecv();
		Date endDate = rentalOrder.getChargeBillRecord().getDateEndRecv();
		SimpleDateFormat sf = new SimpleDateFormat("yyyy-MM-dd");
		String begin = "";
		String end = "";
		
		try{
			begin = sf.format(startDate);
			end = sf.format(endDate);
		}catch(Exception e){
			logger.error("日期格式化出错!");
		}
		
		DaRoom room = rentalOrder.getDaRoom();
		String smsContent = room.getName() + "房租客"
				+ room.getAgreement().getTenantUser().getName() + "，于" + month
				+ "月" + day + "日" + hour + "点" + minute + "分缴租金"
				+ rentalOrder.getTotalFee() + "元（" + begin + "~" + end + "）。"
				+ "因支付宝或微信的公账结算限制,资金将在1至3个工作日转入您的账户。";  
		
		if (smsService.sendMessage(phone,
				SmsLog.TYPE_REMINDER_LETTER, smsContent, true,
				loginUser, SmsService.CHANEL_NORMAL, null) == null) {
			logger.error("短信发送出错");
		} 
		
	}
	
	
	
	/**
	 * 创建支付记录对象
	 * @param rentalOrder
	 * @return
	 */
	private PaymentRecord createPaymentRecord(RentalOrder rentalOrder,String outTradeNo,String customerTradeNo,int payType) {
		
		PaymentRecord payModel = new PaymentRecord();
		
		payModel.setPayState(PaymentRecord.PAY_STATE_SUCCESS);
		payModel.setTradeNo(outTradeNo);
		payModel.setPayType(payType);
		payModel.setOrderType(RaConstant.ORDER_TYPE_RENTAL);
		payModel.setTotalFee(rentalOrder.getTotalFee());
		payModel.setTradeNo(customerTradeNo);
		
		Date date = new Date();
		Timestamp payTime = new Timestamp(date.getTime());
		payModel.setCreateTime(payTime);
		
		return payModel;
	}

 
	
	/**
	 * 网上交租完成后，产生帐务单 daChargeBill
	 * @param order
	 */
	private void createBill(RentalOrder order){
		
		DaChargeBill bill = new DaChargeBill();
		
		bill.setAgreement(null);
		bill.setAmountActual(order.getTotalFee());
		bill.setAmountRecv(order.getTotalFee());
		DaChargeBillRecord chargeBillRecord = order.getChargeBillRecord();
		if(chargeBillRecord == null ){
			chargeBillRecord = new DaChargeBillRecord();
		}
		List<DaChargeItem> chargeItems = chargeBillRecord.getChargeItems();
		if(chargeItems!=null && chargeItems.size() > 0 ){
			for (DaChargeItem daChargeItem : chargeItems) {
				daChargeItem.setChargeBill(bill);
			}
		}
		bill.setChargeItems(chargeItems);
		bill.setDateActual(new Date());
		bill.setAgreement(order.getDaRoom().getAgreement());
		bill.setRoom(order.getDaRoom());
		
		BigDecimal balance = chargeBillRecord.getBalance();
		balance= balance==null? BigDecimal.valueOf(0.00):balance;
		bill.setBalance(balance);
		
		bill.setRemark("网上交租产生的记录");
		bill.setLandlordUser(order.getDaRoom().getLandlordUser());
		genericService.merge(bill);
	}
	
	
	
	/**
	 * 获取关联房间的余额
	 * @param room DaRoom对象 要求必须存在id
	 * @return balance  余额
	 */
	@Rest(type = "search")
	public BigDecimal getRoomBlance(DaRoom room){
		if(room.getAgreement()==null)return BigDecimal.valueOf(0); 
		DaChargeBill example = new DaChargeBill();
		example.setAgreement(room.getAgreement());
		Condition condition = new Condition();
		condition.setSort("id");
		condition.setDir("desc");
		List<DaChargeBill> dbChargeBills = genericService.searchByModel(example, condition).getData();
		if (dbChargeBills.size()>0) {
			DaChargeBill daChargeBill = dbChargeBills.get(0);
			BigDecimal balance = daChargeBill.getBalance();
			balance= balance==null?BigDecimal.valueOf(0):balance;
			return balance;
		}else{
			return BigDecimal.valueOf(0);
		}
		
	}
	
	
	
	/**
	 * 非网上支付的收租需要调用此接口
	 * 场景1：只要是非网上支付的收租，可调用此接口。
	 * 功能： 改变网上收租单的状态为交租成功。
	 * @param room
	 */
	@Rest(type = "update")
	public void paidNoticeFrom(DaRoom room){
		
		if(null==room || room.getId()==null){
			String errStr = "unknow DaRoom or DaRoom.id is null,please check the parameters! ";
			logger.error(errStr);
			throw new RuntimeException(errStr);
		}
		
		RentalOrder order = new RentalOrder();
		order.setDaRoom(room);
		
		PageInfo<RentalOrder> pageInfo = genericService.searchByModel(order, Condition.DEFAULT);
		List<RentalOrder> orders = pageInfo.getData();
		
		if(null != orders && orders.size()>0){
			for (RentalOrder rentalOrder : orders) {
				rentalOrder.setOrderState(RentalOrder.ORDER_STATE_SUCCESS);
				genericService.update(rentalOrder);
			}
		}
		
	}
	@Rest(type = "search")
	public  List<OrderVO> getFeeInfoOfDA(TenantUser model,boolean noPay){
		if(model == null || model.getId()==null){
			throw new RuntimeException("this tenanUser is null or tenanUser.id is null");
		}
		
		//查到该租客下的所有房间
		QLInfo roomQLInfo = new QLInfo();
		String roomSql = "select a from "+ DaRoom.class.getName()+" a  where 1=1";
		roomSql += " and a.agreement is not null and a.agreement.tenantUser is not null";
		roomSql += " and a.agreement.tenantUser.id = ?";
		roomQLInfo.addParam(model.getId());
		roomQLInfo.setQl(roomSql);
		
		@SuppressWarnings("unchecked")
		PageInfo<DaRoom> roomPageInfo = genericService.searchByQl(roomQLInfo);
		
		List<DaRoom> rooms = roomPageInfo.getData();
		List<RentalOrder> resultOders = new ArrayList<RentalOrder>();
		
		LandlordOwnerUser landlordUser = new LandlordOwnerUser();
		if(rooms!=null && rooms.size() > 0 ){
			landlordUser = rooms.get(0).getLandlordUser();
		}
		//查询房间对应的最新一个网上收租单
		for (DaRoom daRoom : rooms) {
			
			QLInfo qlInfo = new QLInfo();
			String orderQL = "select a from " +RentalOrder.class.getName()+" a  where 1=1";
			orderQL += " and a.roomType is not null and a.roomType="+LandlordConstant.ROOMTYPE_DA.intValue() +"";
			if(noPay){
				orderQL += " and a.orderState = ?";
				qlInfo.addParam(RentalOrder.ORDER_STATE_WAITING_PAYMENT);//未支付
			}else{
				orderQL += " and a.orderState in (?,?,?)";
				// 已支付
				qlInfo.addParam(RentalOrder.ORDER_STATE_PAYING);
				qlInfo.addParam(RentalOrder.ORDER_STATE_PAYMENTED);
				qlInfo.addParam(RentalOrder.ORDER_STATE_SUCCESS);
			}
			
			orderQL += " and a.daRoom is not null and a.daRoom.id = ?";
			qlInfo.addParam(daRoom.getId());
			qlInfo.setPageInfo(0, 1, "a.id", "desc");
			qlInfo.setQl(orderQL);
			
			@SuppressWarnings("unchecked")
			PageInfo<RentalOrder> orderQLInfo = genericService.searchByQl(qlInfo);
			List<RentalOrder> orders = orderQLInfo.getData();
			if(orders.size()>0){
				RentalOrder rentalOrder = orders.get(0);
				
				if(rentalOrder != null ){
					resultOders.add(rentalOrder);
				}
			}
		}
		
		List<OrderVO> orders = new ArrayList<OrderVO>();
		for (RentalOrder order : resultOders) {
			
			OrderVO vo = getNoPayOrderVO(order);
			orders.add(vo);
			
		}
		return orders;
	}
	
	/**
	 * 根据RentalOrder获取OrderVO
	 * @param order
	 * @return
	 */
	@Rest(type = "search")
	public  OrderVO getNoPayOrderVO(RentalOrder order){
		SimpleDateFormat sf = new SimpleDateFormat("yyyy.MM.dd");
		OrderVO vo = new OrderVO();
		DaRoom daRoom = order.getDaRoom();
		DaSuite suite = daRoom.getSuite();
		String roomName = daRoom.getName();
		
		if (suite.getRentType() != null && DaSuite.RENT_TYPE_SUB == suite.getRentType()) {
			roomName = suite.getName() + "-" + daRoom.getName();
		}
		
		BigDecimal totalFee = new BigDecimal(0.0);
		LandlordOwnerUser landlordUser = new LandlordOwnerUser();
		landlordUser = daRoom.getLandlordUser();
		vo.setRental(daRoom.getRentPay());
		vo.setLandlordUser(landlordUser);
		vo.setOutTradeNo(order.getOutTradeNo());
		vo.setOrderState(order.getOrderState());
		vo.setOrderId(order.getId());
		vo.setTotalFee(order.getTotalFee());
		vo.setRoomName(roomName);
		vo.setRoomId(order.getDaRoom().getId());
		
		vo = commonService.completeOrderVO(vo);
		
		List<DaChargeItem> chargeItems = order.getChargeBillRecord().getChargeItems();
		List<OrderItemsVO> orderItems = new ArrayList<OrderItemsVO>();
		List<OrderItemsVO> meterAndTotalItems = new ArrayList<OrderItemsVO>();
		
		for (DaChargeItem daChargeItem : chargeItems) {
			
			OrderItemsVO item = new OrderItemsVO();
			if(daChargeItem.getChargeType().equals(DaChargeItem.CHARGE_TYPE_RENTAL)){
				vo.setStartDate(sf.format(daChargeItem.getDateBeginRecv()));
				vo.setEndDate(sf.format(daChargeItem.getDateEndRecv()));
			}else if(daChargeItem.getChargeType().equals(DaChargeItem.CHARGE_TYPE_METER)){
				
				try{
					DaMeter meter2 = daChargeItem.getMeter2();
					DaMeter meter1 = daChargeItem.getMeter1();
					DaFeeRule feeRule = meter2.getFeeRule();
					String unit = feeRule.getFeeRuleCfg().getFeeRuleCfgDesc().getUnit();
					BigDecimal price = feeRule.getFeeRuleCfg().getFeeRuleCfgCalc().getPrice();
					//当前刻度与前一次的度数
					item.setCurrMeterCount(meter2.getCount());
					item.setPreMeterCount(meter1.getCount());
					//获取单价
					item.setUnit(unit);
					item.setUnitPrice(price);
					item.setType(DaChargeItem.CHARGE_TYPE_METER);
					meterAndTotalItems.add(item);
				}catch(Exception e){
					throw new RuntimeException("无法取到仪表费用的单价和单位!");
				}
			}
			item.setPrice(daChargeItem.getPriceRecv());
			item.setStartDate(sf.format(daChargeItem.getDateBeginRecv()));
			item.setEndDate(sf.format(daChargeItem.getDateEndRecv()));
			item.setChargeItemId(daChargeItem.getId());
			item.setName(daChargeItem.getName());
			totalFee = totalFee.add(item.getPrice());
			orderItems.add(item);
		}
		OrderItemsVO totalFeeItem = new OrderItemsVO();
		totalFeeItem.setName("总费用");
		totalFeeItem.setPrice(totalFee);
		meterAndTotalItems.add(totalFeeItem);
		vo.setMeterItems(meterAndTotalItems);
		vo.setItems(orderItems);
		BigDecimal roomBlance = getRoomBlance(order.getDaRoom());
		vo.setBalance(roomBlance);
		return vo;
	}
	
}
